#!/usr/bin/env python3
import json
import socket
import syslog
import threading
import time
import os
VERSION=1.1

# for debug
import pdb



class config:
    # expects config in /etc/
    def __init__(self, conffile='/etc/portmine.conf'):
        self.log = True
        self.logPath = "/var/log/portmine.log"
        try:
            jsonData = open(conffile)
            self.configData = json.load(jsonData)
            jsonData.close()
        except Exception as e:
            try:
                log = open(self.logPath, 'a')
                log.write("PortMine Error: %s\n" %(e))
                log.close()
            except IOError:
                print("Cant write to logfile %s\n" %(self.logPath))
    
    def getConfig(self):
        # return config data
        conf = self.configData["portmineConf"]
        conf['port'] = conf['port'].split(",")
        log = open(self.logPath, 'a')
        msg = "portMine started at %s\n" %(time.strftime('%Y%m%d%H%M%S'))
        log.write(msg)
        syslog.syslog(msg)
        msg = "portMine started with following config %s\n" %(conf)
        log.write(msg)
        syslog.syslog(msg)
        log.close()
        if conf["syslog"] != "True" or conf["log"] != "True":
            print("You have no logging enabled, set your config syslog or log to True")
        return conf

class honeyLog:
    # normal log file
    def __init__(self, config):
        self.logPath = config["logdir"]
        self.log = None
        self.mlog = config['log'].lower()
        self.slog = config['syslog'].lower()

    def openLog(self):
        # open normal log file
        if os.path.isfile(self.logPath): 
            self.log = open(self.logPath, 'a')
        else:
            print("Error writing to logfile %s" %(self.logPath))
            exit(-1)
    
    def write(self, msg):
        # write to normal and syslog based on config
        if self.mlog == 'true':
            if os.path.isfile(self.logPath):
                with open(self.logPath, 'a') as log:
                    log.write("%s %s" %(time.strftime('%Y%m%d%H%M%S'), msg))
        if self.slog == 'true':
            syslog.syslog(msg)


class honeyPort(threading.Thread):
    def __init__(self, port, host, whitelist, logging):
        threading.Thread.__init__(self)
        threading.Thread.daemon = True
        # set up a socket
        self.HOST = host
        self.PORT = int(port)
        self.whitelist = whitelist
        self.logging = logging
        if config["socket"] == "tcp":
            self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        elif config["socket"] == "udp":
            self.s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.s.bind((self.HOST, self.PORT))
        self.logging.write('portMine %s has started listening on %s\n' %(VERSION, self.PORT))
        self.s.listen(1)

    def run(self):
        # listen and report
        try:
            while True:
                conn, addr = self.s.accept()
                # for debug
                # print('Honey Port Connected by', addr)
                if addr[0] not in self.whitelist:
                    self.logging.write('Honey Port Connected by %s on port %s\n' %(addr[0], self.PORT))
                conn.close()
        except KeyboardInterrupt:
            self.stop()

    def stop(self):
        self.logging.write('portMine has stopped listening on port %s\n' %(self.PORT))
        self.s.close()
        self.slog.stop()

if __name__ == "__main__":
    config = config().getConfig()
    logging = honeyLog(config)
    threadList = []
    for port in config["port"]:
        pm = honeyPort(port, config['host'], config["whitelist"], logging)
        pm.start()
        threadList.append(pm)
    while True:
        # wait for a kill signal
        time.sleep(.5)
